package com.tencent.welink.util;


import com.tencent.weling.proto.VideoGateWayPB;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.security.MessageDigest;

/**
 * Created by junchihe on 2018/3/16.
 */
public class FrameData {

    private final byte[] data;
    private final int sequence;
    private final long timestamp;
    private final int vcodertype;//1 h264 2h265
    private final int acodertype;
    private final int keyframe;//1 key frame
    private final int avtype; // == 1; video type 1,audio type 2
    private final int streamId;
    private final int subdin;
    private final long din;

    public String getRecordHandler() {
        return recordHandler;
    }

    private final String recordHandler;

    public byte[] getData() {
        return data;
    }

    public int getSequence() {
        return sequence;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public int getVcodertype() {
        return vcodertype;
    }

    public int getKeyframe() {
        return keyframe;
    }

    public int getAvtype() {
        return avtype;
    }

    public int getAcodertype(){return acodertype;}

    public int getStreamId() {
        return streamId;
    }

    public int getSubdin() {
        return subdin;
    }

    public long getDin() {
        return din;
    }

    private static final Logger log = LogManager.getLogger(FrameData.class);
    /*
    optional uint64 uint64_din          = 1;    //摄像头din
    optional uint32 uint32_sub_id       = 2;    //子设备ID
    optional uint32 uint32_version      = 3;    //协议版本号：0至2，表示不加密，3、表示AES128 ecb加密，4表示SM4 cbc加密data
    optional uint32 uint32_stream_id    = 4;    //通道类型：0-主码流，1~0x0e-辅码流(其中0x0e固定为抽帧流)，0x0f-录像音视频 0x0d-本地录像
    optional uint32 uint32_pkg_type     = 5;    //报文类型：0-数据包，1-握手请求包，2-握手回包
    optional uint32 uint32_video_type   = 6;    //视频编码类型：1-H264，2-H265, 0xffff-其他
    optional uint32 uint32_audio_type   = 7;    //音频编码类型：1-AMR，2-AAC，6-G711, 0xffff-其他
    optional uint32 uint32_seq          = 8;    //序列号，请求和响应相同
    optional uint64 uint64_timestamp    = 9;    //时间戳
    optional uint32 uint32_data_type    = 10;   //音视频类型：1-视频，2-音频，0xF-(结束包，表示音视频结束，连接可以断开)
    optional uint32 uint32_frame_type   = 11;   //视频帧类型：1-关键帧，2-非关键帧
	optional bytes token                =12;    //token用于验证接入权限，只限握手包使用
	optional uint32 uint32_encrypted_len = 13;  //加密数据长度
	optional uint32 uint32_encrypted_type = 14; //加密类型,0，表示不加密，1表示AES128加密，只限握手包使用
	//以下专为本地录像所加
	optional bytes recordHandler     = 15;    //recordHandler unique id for video record
	optional uint64 timeBegin        = 16;    //代表哪一时间段内拉流开始
	optional uint64 timeEnd          = 17;    //代表哪一时间段内拉流结束
    optional uint32 frameRate        = 18;    //事件基本信息
	optional uint32 width            = 19;    //视频宽
    optional uint32 height           = 20;   //视频高
	optional bytes md5               = 21;   //bodyData字段MD5值
     */

    public FrameData(byte[] data, int sequence,int acodertype,int vcodertype,int keyframe,int avtype,int streamId,long din,int subdin){

        this.data = data;
        this.sequence = sequence;//sequence;
        this.timestamp = System.currentTimeMillis();
        //this.timestamp = System.currentTimeMillis();
        this.acodertype = acodertype;
        this.vcodertype = vcodertype;
        this.keyframe = keyframe;
        this.avtype = avtype;
        this.streamId = streamId;
        this.din = din;
        this.subdin = subdin;
        this.recordHandler = "";
        if(this.keyframe==1)
        log.info("din={},streamId={},keyframe={},avtype={},size={}",this.din,this.streamId,this.keyframe,this.avtype,this.data.length);

    }
   /* public FrameData(byte[] data, PbforpushV2.MvsHead mvsHead){
        this.data = data;
        this.sequence = mvsHead.getUint32Seq();//sequence;
        this.timestamp = mvsHead.getUint64Timestamp();
        //this.timestamp = System.currentTimeMillis();
        this.acodertype = mvsHead.getUint32AudioType();
        this.vcodertype = mvsHead.getUint32VideoType();
        this.keyframe = mvsHead.getUint32FrameType();
        this.avtype = mvsHead.getUint32DataType();
        this.streamId = mvsHead.getUint32PipeType();
        this.din = mvsHead.getUint64Din();
        this.subdin = mvsHead.getUint32SubId();

    }*/



    /*public FrameData(ByteBuf readBuf, int totalLen, VideoGateWayPB.MvsHead mvsHead, IEncryptAndDecrypt aes128){
        this.data = FrameData.getBytes(readBuf,totalLen,mvsHead.getUint32EncryptedLen(),aes128);
        this.sequence = mvsHead.getUint32Seq();//sequence;
        this.timestamp = mvsHead.getUint64Timestamp();
        //this.timestamp = System.currentTimeMillis();
        this.acodertype = mvsHead.getUint32AudioType();
        this.vcodertype = mvsHead.getUint32VideoType();
        this.keyframe = mvsHead.getUint32FrameType();
        this.avtype = mvsHead.getUint32DataType();
        this.streamId = mvsHead.getUint32StreamId();
        this.din = mvsHead.getUint64Din();
        this.subdin = mvsHead.getUint32SubId();

    }*/
    public FrameData(ByteBuf readBuf, String recordHandler, int totalLen, VideoGateWayPB.MvsHead eventHeadPB, IEncryptAndDecrypt aes128, int data_en_len){
        this.data = EventUtil.getBytes(readBuf,totalLen,data_en_len,aes128);
        //JSONObject jsonObject = JSONObject.parseObject(eventHeadPB.getEventBaseInfo().toStringUtf8());

        this.sequence = eventHeadPB.getUint32Seq();

        this.timestamp = eventHeadPB.getUint64Timestamp();
        //this.timestamp = System.currentTimeMillis();
        this.acodertype = eventHeadPB.getUint32AudioType();
        this.vcodertype =eventHeadPB.getUint32VideoType();
        //this.keyframe = eventHeadPB.getUint32FrameType();
        this.avtype = eventHeadPB.getUint32DataType();
        this.streamId = eventHeadPB.getUint32StreamId();
        this.din = eventHeadPB.getUint64Din();
        this.subdin = eventHeadPB.getUint32SubId();
        this.recordHandler = recordHandler;
        if(this.avtype == 1)
            this.keyframe = eventHeadPB.getUint32FrameType();
        else
            this.keyframe = 0;

    }

    public  void write(ByteBuf byteBuf) {
        if(data!= null && data.length>0 && byteBuf != null) {
            byteBuf.writeBytes(data);
        }
    }

    public int size() {
        if(data == null) return 0;
        return data.length;
    }


    public void updateMD5(MessageDigest md5) {
        md5.update(data);
    }

//    public ChannelFuture writeAndFlush(ChannelHandlerContext ctx, ByteEncrypt byteEncrypt, VideoGateWayPB.MvsHead.Builder mh) {
//        byteEncrypt.buildData(getData());
//        //mh.setUint32AudioType(getAcodertype());
//        mh.setUint32DataType(getAvtype());
//        mh.setUint32FrameType(getKeyframe());
//        //mh.setUint32StreamId(getStreamId());
//        //mh.setUint32PkgType(0);
//        mh.setUint32EncryptedLen(byteEncrypt.getEncryptedLength());
//        //mh.setUint32EncryptedType(encyrptedType);
//
//        //mh.setUint64Din(getDin());
//        mh.setUint64Timestamp(getTimestamp());
//        //Log.log(log,fd.getDin() + " ======" + fd.getTimestamp());
//        //mh.setUint32SubId(getSubdin());
//        //mh.setUint32Version(version);
//        //mh.setUint32VideoType(getVcodertype());
//        mh.setUint32Seq(getSequence());
//        mh.setUint32EncryptedLen(byteEncrypt.getEncryptedLength());
//        byte[] mhb = mh.build().toByteArray();
//        int bodylen = byteEncrypt.getLength();
//        ByteBuf bf = ctx.alloc().buffer(16 + mhb.length +  bodylen);
//
//        bf.writeByte(CompileBufferDecoder.clientBegin);
//        bf.writeByte(CompileBufferDecoder.clientBegin);
//        bf.writeByte(CompileBufferDecoder.clientBegin);
//        bf.writeByte(CompileBufferDecoder.clientBegin);
//        bf.writeInt(mhb.length);
//        bf.writeInt(bodylen);
//        bf.writeBytes(mhb);
//        //bf.writeBytes(fd.getData());
//        byteEncrypt.writeData(bf);
//        bf.writeByte(CompileBufferDecoder.end);
//        bf.writeByte(CompileBufferDecoder.end);
//        bf.writeByte(CompileBufferDecoder.end);
//        bf.writeByte(CompileBufferDecoder.end);
//        //ctx.writeAndFlush(bf);
//        return ctx.writeAndFlush(bf);
//    }

}
